package com.controller.sys.role;

import com.common.ErrorCodeEnum;
import com.model.base.PageResult;
import com.model.base.Result;
import com.common.anntation.Log;
import com.common.emums.BusinessType;
import com.common.emums.DataScopeType;

import com.common.exception.BusinessException;
import com.common.utils.EntityConversionUtil;
import com.common.utils.StringUtils;
import com.core.springSecurity.service.PermissionService;
import com.model.domain.sys.GetRoleListDO;
import com.model.dto.sys.roleController.CreateRoleDTO;
import com.model.dto.sys.roleController.GetRoleListDTO;
import com.model.dto.sys.roleController.UpdateRoleListDTO;
import com.model.dto.sys.roleController.UpdateRoleStatusDTO;
import com.github.pagehelper.PageInfo;
import com.model.pojo.sys.SysDept;
import com.model.pojo.sys.SysMenu;
import com.model.pojo.sys.SysRole;
import com.model.vo.sys.menu.GetSysMenuVO;
import com.service.sys.SysRoleDeptService;
import com.service.sys.SysRoleMenuService;
import com.service.sys.SysRoleService;
import com.service.sys.SysUserRoleService;
import com.model.vo.sys.dept.DeptVO;
import com.model.vo.sys.role.RoleVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 角色管理
 */
@Api(tags = {"角色"})
@Slf4j
@RestController
@RequestMapping("/v1")
public class RoleController {

    @Resource
    SysRoleService sysRoleService;

    @Resource
    SysUserRoleService sysUserRoleService;

    @Resource
    SysRoleDeptService sysRoleDeptService;

    @Resource
    SysRoleMenuService sysRoleMenuService;

    /**
     * @param createRoleDTO 角色参数
     * @Author: zql
     * @Description: 创建角色
     * @Data: 14:47 2021/7/5
     */
    @ApiOperation(value = "创建角色")
    @Log(title = "创建角色", businessType = BusinessType.INSERT)
    @PostMapping("/createRole")
    @PreAuthorize("@ss.hasAnyPermi('" + PermissionService.SYSTEM_OPERATE + "')")
    public Result<Objects> createRole(@RequestBody @Valid CreateRoleDTO createRoleDTO) {
        /* 检查权限字段合法性 */
        if (!PermissionService.hasPermission(createRoleDTO.getPermissions())) {
            throw new BusinessException(ErrorCodeEnum.PERMISSIONS_NAME_FAILED);
        }
        /* 如果有绑定用户检查用户是否存在 */
        if (StringUtils.isNotNull(createRoleDTO.getSysUserIds())) {
            sysUserRoleService.verifySysUserId(createRoleDTO.getSysUserIds());
        }
        /* 如果是自定义数据权限需检查绑定的部门是否存在*/
        if (DataScopeType.DATA_SCOPE_CUSTOM.equals(createRoleDTO.getDataScope())) {
            sysRoleDeptService.verifySysDeptId(createRoleDTO.getDeptIds());
        }
        /* 如果有绑定菜单检查菜单是否存在 */
        if (StringUtils.isNotNull(createRoleDTO.getMenuIds())) {
            sysRoleMenuService.verifySysMenuId(createRoleDTO.getMenuIds());
        }
        /* 创建角色 */
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(createRoleDTO, sysRole);
        sysRole.setApiKey(SysRoleService.getKey(createRoleDTO.getPermissions()));
        sysRole.setButtonKey(SysRoleService.getKey(createRoleDTO.getButtons()));
        sysRoleService.create(sysRole);
        /* 绑定角色与用户 */
        if (StringUtils.isNotNull(createRoleDTO.getSysUserIds())) {
            sysUserRoleService.bindingRole(sysRole.getSysRoleId(), createRoleDTO.getSysUserIds());
        }
        /* 如果是自定义数据权限就绑定部门 */
        if (DataScopeType.DATA_SCOPE_CUSTOM.equals(createRoleDTO.getDataScope())) {
            sysRoleDeptService.binding(sysRole.getSysRoleId(), createRoleDTO.getDeptIds());
        }
        /* 绑定角色与菜单 */
        if (StringUtils.isNotNull(createRoleDTO.getMenuIds())) {
            sysRoleMenuService.binding(sysRole.getSysRoleId(), createRoleDTO.getMenuIds());
        }
        return Result.suc();
    }

    /**
     * @param getRoleListDTO 查询参数
     * @Author: zql
     * @Description: 查询角色列表
     * @Data: 15:00 2021/7/5
     */
    @ApiOperation(value = "查询角色列表")
    @PostMapping("/getRoleList")
    @PreAuthorize("@ss.hasAnyPermi('" + PermissionService.SYSTEM_OPERATE + "')")
    public Result<PageResult<List<RoleVO>>> getRoleList(@RequestBody @Valid GetRoleListDTO getRoleListDTO) {
        GetRoleListDO getRoleListDO=EntityConversionUtil.copy(getRoleListDTO,GetRoleListDO.class);
        List<SysRole> sysRoleList = sysRoleService.getRoleList(getRoleListDO);
        PageInfo<SysRole> pageInfo = new PageInfo<>(sysRoleList);
        List<RoleVO> roleVOList = new ArrayList<>();
        sysRoleList.forEach(sysRole -> {
            RoleVO roleVo = new RoleVO();
            BeanUtils.copyProperties(sysRole, roleVo);
            /* 如果是自定义数据权限则查询部门列表 */
            if (DataScopeType.DATA_SCOPE_CUSTOM.equals(sysRole.getDataScope())) {
                List<SysDept> sysDeptList = sysRoleDeptService.getDeptListByRoleId(sysRole.getSysRoleId());
                List<DeptVO> deptVOList = EntityConversionUtil.copyList(sysDeptList, DeptVO.class);
                roleVo.setDeptList(deptVOList);
            }
            else{
                roleVo.setDeptList(new ArrayList<>());
            }
            roleVo.setUserCount(sysUserRoleService.getUserCount(sysRole.getSysRoleId()));
            /* 如有必要显示与角色绑定的菜单列表 */
            if (StringUtils.isNotNull(getRoleListDTO.getContainMenu()) && getRoleListDTO.getContainMenu()) {
                List<SysMenu> sysMenuList = sysRoleMenuService.getMenuList(sysRole.getSysRoleId());
                List<GetSysMenuVO> menuVOList = EntityConversionUtil.copyList(sysMenuList, GetSysMenuVO.class);
                roleVo.setMenuList(menuVOList);
            }else{
                roleVo.setMenuList(new ArrayList<>());
            }
            /* 权限分组显示 */
            roleVo.setButtonSet(SysRoleService.getKeySet(sysRole.getButtonKey()));
            roleVo.setPermissionSet(SysRoleService.getKeySet(sysRole.getApiKey()));
            roleVOList.add(roleVo);
        });

        PageResult<List<RoleVO>> build = PageResult.<List<RoleVO>>builder().result(roleVOList).pageInfo(pageInfo).build();
        return Result.suc(build);
    }

    /**
     * @param updateRoleListDTO 更新参数
     * @Author: zql
     * @Description: 批量更新角色信息
     * @Data: 17:54 2021/5/11
     */
    @ApiOperation(value = "批量更新角色信息")
    @Log(title = "批量更新角色信息", businessType = BusinessType.UPDATE)
    @PostMapping("/updateRoleList")
    @PreAuthorize("@ss.hasAnyPermi('" + PermissionService.SYSTEM_OPERATE + "')")
    public Result<Object> updateRoleStatusList(@RequestBody @Valid UpdateRoleListDTO updateRoleListDTO) {
        List<SysRole> sysRoleList = new ArrayList<>();
        for (UpdateRoleListDTO.RoleInfo roleInfo : updateRoleListDTO.getRoleInfoSet()) {
            /* 参数合法性校验 */
            if (StringUtils.isNotNull(roleInfo.getPermissions())
                    && !PermissionService.hasPermission(roleInfo.getPermissions())) {
                throw new BusinessException(ErrorCodeEnum.PERMISSIONS_NAME_FAILED);
            }
            if (StringUtils.isNotNull(roleInfo.getSysUserIds())) {
                sysUserRoleService.verifySysUserId(roleInfo.getSysUserIds());
            }
            if (DataScopeType.DATA_SCOPE_CUSTOM.equals(roleInfo.getDataScope())) {
                sysRoleDeptService.verifySysDeptId(roleInfo.getDeptIds());
            }
            if (StringUtils.isNotNull(roleInfo.getMenuIds())) {
                sysRoleMenuService.verifySysMenuId(roleInfo.getMenuIds());
            }
            SysRole sysRole = sysRoleService.get(roleInfo.getSysRoleId(),null);
            sysRole.setName(roleInfo.getName());
            sysRole.setDataScope(roleInfo.getDataScope());
            sysRole.setSynopsis(roleInfo.getSynopsis());
            if(StringUtils.isNotNull(roleInfo.getPermissions()) ) {
                sysRole.setApiKey(SysRoleService.getKey(roleInfo.getPermissions()));
            }
            if(StringUtils.isNotNull(roleInfo.getButtons()) ) {
                sysRole.setButtonKey(SysRoleService.getKey(roleInfo.getButtons()));
            }
            sysRoleList.add(sysRole);
        }

        updateRoleListDTO.getRoleInfoSet().forEach(roleInfo -> {
            if (StringUtils.isNotNull(roleInfo.getSysUserIds())) {
                sysUserRoleService.uBindList(roleInfo.getSysRoleId());
                sysUserRoleService.bindingRole(roleInfo.getSysRoleId(), roleInfo.getSysUserIds());
            }

            if (DataScopeType.DATA_SCOPE_CUSTOM.getCode().equals(roleInfo.getDataScope())) {
                sysRoleDeptService.uBindList(roleInfo.getSysRoleId());
                sysRoleDeptService.binding(roleInfo.getSysRoleId(), roleInfo.getDeptIds());
            }

            if (StringUtils.isNotNull(roleInfo.getMenuIds())) {
                sysRoleMenuService.uBindList(roleInfo.getSysRoleId());
                sysRoleMenuService.binding(roleInfo.getSysRoleId(),roleInfo.getMenuIds());
            }
        });

        if (sysRoleList.size() > 0) {
            sysRoleService.updateList(sysRoleList);
        }
        return Result.suc();
    }

    @ApiOperation(value = "修改角色状态")
    @Log(title = "修改角色状态", businessType = BusinessType.UPDATE)
    @PostMapping("/updateRoleStatus")
    @PreAuthorize("@ss.hasAnyPermi('" + PermissionService.SYSTEM_OPERATE + "')")
    public Result<Objects> updateRoleStatus(@RequestBody @Valid UpdateRoleStatusDTO updateRoleStatusDTO) {
        if(1 == updateRoleStatusDTO.getSysRoleId()){
            throw new BusinessException(ErrorCodeEnum.ROOT_ROLE);
        }
        sysRoleService.get(updateRoleStatusDTO.getSysRoleId(),null);
        SysRole sysRole = new SysRole();
        sysRole.setSysRoleId(updateRoleStatusDTO.getSysRoleId());
        sysRole.setIsDelete(updateRoleStatusDTO.getIsDelete());
        sysRoleService.update(sysRole);
        return Result.suc();
    }
}
